home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / src / dd / cexp.c < prev    next >
C/C++ Source or Header  |  1997-09-09  |  14KB  |  725 lines

  1. /*
  2.  *    (c)Copyright 1992-1997 Obvious Implementations Corp.  Redistribution and
  3.  *    use is allowed under the terms of the DICE-LICENSE FILE,
  4.  *    DICE-LICENSE.TXT.
  5.  */
  6. /*
  7.  *  CEXP.C
  8.  */
  9. #include    "defs.h"
  10. #include    "dbug_protos.h"
  11.  
  12.  
  13. Prototype long        ParseExp(char *, short *, long);
  14.  
  15. Prototype void        PushOp(short, short, short);
  16. Prototype int        TopOfOpStack(void);
  17. Prototype int        SecondOffOpStack(void);
  18. Prototype void        PushAtom(long, short);
  19.  
  20. Local int        CombineOp(void);
  21. Local int        GetAtomStack(short *, long *);
  22. Local int        ParseCharConst(char *, long, long, long *);
  23. Local int        ParseInt(char *, long, long, long *);
  24. Local int        HexDig(char);
  25. Local int        OctDig(char);
  26. Local short        SymbolChar(short);
  27. Local long        ExtSymbol(unsigned char *, long, long);
  28.  
  29.  
  30. #define MAXATOM     128
  31. #define MAXOPER     128
  32.  
  33. #define CGTEQ    256
  34. #define CGTGT    257
  35. #define CLTEQ    258
  36. #define CLTLT    259
  37. #define CNOTEQ    260
  38. #define CEQEQ    261
  39. #define CSYM    262
  40. #define CUMI    263
  41. #define CUIND    264
  42.  
  43. #define CDEFINED    280
  44. #define CANDAND     281
  45. #define COROR        282
  46.  
  47. #define QBIN    4        /*    binary operator, else unary */
  48. #define LR    1        /*    left to right, else        */
  49. #define RL    2        /*    right to left            */
  50. #define BLR    (LR|QBIN)
  51. #define BRL    (RL|QBIN)
  52. #define XX    0
  53.  
  54. typedef struct Atom {
  55.     long    Value;
  56.     short   Undef;
  57.     short   Reserved;
  58. } Atom;
  59.  
  60. typedef struct Oper {
  61.     short   Token;
  62.     short   Pri;
  63.     short   Type;
  64.     short   Reserved;
  65. } Oper;
  66.  
  67. static Atom AtomStack[MAXATOM];
  68. static Oper OperStack[MAXOPER];
  69. static short AtomIdx;
  70. static short OperIdx;
  71. static short BaseAtomIdx;
  72. static short BaseOperIdx;
  73.  
  74. long ParseExp(char *buf, short *pundef, long max)
  75. {
  76.     short unary = 1;
  77.     short i = 0;
  78.     short parens = 0;
  79.     short baseOperIdx;
  80.     short baseAtomIdx;
  81.  
  82.     baseOperIdx = BaseOperIdx = OperIdx;
  83.     baseAtomIdx = BaseAtomIdx = AtomIdx;
  84.  
  85.     while (i < max) {
  86.     short c = buf[i];
  87.  
  88.     ++i;
  89.     if (c == ' ' || c == 9 || c == '\n')
  90.         continue;
  91.  
  92.     if (unary) {    /*  int, sym, !exp, ~exp (exp), *exp  */
  93.         switch(c) {
  94.         case '*':   /*  indirection */
  95.         PushOp(CUIND, 140, RL);
  96.         break;
  97.         case '!':
  98.         case '~':
  99.         PushOp(c, 140, RL);
  100.         break;
  101.         case '-':
  102.         PushOp(CUMI, 140, RL);
  103.         break;
  104.         case '(':
  105.         ++parens;
  106.         PushOp(c, 0, XX);
  107.         break;
  108.         default:
  109.         if (c >= '0' && c <= '9') {
  110.             long v;
  111.             i = ParseInt(buf, i - 1, max, &v);
  112.             PushAtom(v, 0);
  113.             unary = 0;
  114.             break;
  115.         }
  116.  
  117.         if (SymbolChar(c)) {
  118.             short    ni;
  119.             long    v;
  120.             long    *rptr;
  121.  
  122.             --i;
  123.             ni = ExtSymbol(buf, i, max);    // extract symbol
  124.             if (i + 2 == ni && (rptr = RegisterAddress(buf + i))) {
  125.                 PushAtom(*rptr, 0);
  126.                 unary = 0;
  127.                 i = ni;
  128.                 break;
  129.             } 
  130.             else if (LookupSymLen(buf + i, ni-i, &v)) {
  131.                 PushAtom(v, 0);
  132.                 unary = 0;
  133.                 i = ni;
  134.                 break;
  135.             }
  136.  
  137.             else if (LookupSymLen(addscore(buf + i), ni-i+1, &v)) {
  138.                 PushAtom(v, 0);
  139.                 unary = 0;
  140.                 i = ni;
  141.                 break;
  142.             }
  143.  
  144.             else if (LookupSymLen(addat(buf + i), ni-i+1, &v)) {
  145.                 PushAtom(v, 0);
  146.                 unary = 0;
  147.                 i = ni;
  148.                 break;
  149.             }
  150.  
  151.             i++;
  152.         }
  153.  
  154. #ifdef MYKE_REMOVED_THIS
  155.         /*
  156.          *  NOTE, handles 'defined' by pushing unary op instead
  157.          *      of atom.
  158.          */
  159.  
  160.         if (SymbolChar(c)) {    /*  SymbolChar() includes '0'-'9'   */
  161.             short ni;
  162.  
  163.             --i;
  164.             ni = ExtSymbol(buf, i, max);    /*    extract symbol */
  165.             if (ni - i == 7 && strncmp(buf + i, "defined", 7) == 0) {
  166.             PushOp(CDEFINED, 140, RL);
  167.             } else if (TopOfOpStack() == CDEFINED || SecondOffOpStack() == CDEFINED) {
  168.             Sym *sym = FindSymbol(buf + i, ni - i);
  169.             if (sym)
  170.                 PushAtom(1, 0);
  171.             else
  172.                 PushAtom(0, 1);
  173.             unary = 0;
  174.             } else {
  175.             Sym *sym = FindSymbol(buf + i, ni - i);
  176.  
  177.             if (sym) {
  178.                 short xundef;
  179.                 long v;
  180.  
  181.                 v = ParseExp(sym->Text, &xundef, sym->TextLen);
  182.                 BaseOperIdx = baseOperIdx;
  183.                 BaseAtomIdx = baseAtomIdx;
  184.                 PushAtom(v, xundef);
  185.             } else {
  186.                 PushAtom(0, 1);
  187.             }
  188.             unary = 0;
  189.             }
  190.             i = ni;
  191.             break;
  192.         }
  193. #endif
  194.         if (c == '\'') {
  195.             long v;
  196.             i = ParseCharConst(buf, i - 1, max, &v);
  197.             PushAtom(v, 0);
  198.             unary = 0;
  199.             break;
  200.         }
  201. syntax:
  202.         ScrStatus(("*** syntax error"));
  203. syntax2:
  204.         *pundef = 1;
  205.         AtomIdx = baseAtomIdx;
  206.         OperIdx = baseOperIdx;
  207.         return(0);
  208.         }
  209.     }
  210.     else {    /*  + - * / % & | ^ <= << < == != > >> >=   */
  211.         unary = 1;
  212.  
  213.         switch(c) {
  214.         case '+':
  215.         case '-':
  216.         PushOp(c, 120, BLR);
  217.         break;
  218.         case '*':
  219.         case '/':
  220.         case '%':
  221.         PushOp(c, 130, BLR);
  222.         break;
  223.         case '&':
  224.         if (i < max && buf[i] == '&') {
  225.             PushOp(CANDAND, 50, BLR);
  226.             ++i;
  227.         } else {
  228.             PushOp(c, 60, BLR);
  229.         }
  230.         break;
  231.         case '^':
  232.         PushOp(c, 70, BLR);
  233.         break;
  234.         case '|':
  235.         if (i < max && buf[i] == '|') {
  236.             ++i;
  237.             PushOp(COROR, 40, BLR);
  238.         } else {
  239.             PushOp(c, 80, BLR);
  240.         }
  241.         break;
  242.         case '<':
  243.         if (i < max) {
  244.             short d = buf[i];
  245.             if (d == '<') {
  246.             PushOp(CLTLT, 110, BLR);
  247.             ++i;
  248.             break;
  249.             }
  250.             if (d == '=') {
  251.             PushOp(CLTEQ, 100, BLR);
  252.             ++i;
  253.             break;
  254.             }
  255.         }
  256.         PushOp(c, 100, BLR);
  257.         break;
  258.         case '=':
  259.         if (i >= max || buf[i] != '=')
  260.             goto syntax;
  261.         PushOp(CEQEQ, 90, BLR);
  262.         ++i;
  263.         break;
  264.         case '!':
  265.         if (i >= max || buf[i] != '=')
  266.             goto syntax;
  267.         PushOp(CNOTEQ, 90, BLR);
  268.         ++i;
  269.         break;
  270.         case '>':
  271.         if (i < max) {
  272.             short d = buf[i];
  273.             if (d == '>') {
  274.             PushOp(CGTGT, 110, BLR);
  275.             ++i;
  276.             break;
  277.             }
  278.             if (d == '=') {
  279.             PushOp(CGTEQ, 100, BLR);
  280.             ++i;
  281.             break;
  282.             }
  283.         }
  284.         PushOp(c, 100, BLR);
  285.         break;
  286.         case ')':
  287.         unary = 0;
  288.         if (parens == 0) {
  289.             ScrStatus(("*** Too many close parens"));
  290.             goto syntax2;
  291.         }
  292.         --parens;
  293.         while ((c = TopOfOpStack()) && c != '(')
  294.             CombineOp();
  295.         if (c == 0)goto syntax;
  296.         CombineOp();
  297.         break;
  298.         default:
  299.         goto syntax;
  300.         }
  301.     }
  302.     }
  303.     while (TopOfOpStack() >= 0 && CombineOp() >= 0)
  304.     ;
  305.  
  306.     if (TopOfOpStack() >= 0)goto syntax;
  307.  
  308.     {
  309.     long v;
  310.  
  311.     if (GetAtomStack(pundef, &v) < 0)goto syntax;
  312.     if (GetAtomStack(NULL, NULL) >= 0)goto syntax;  // shouldn't be anything left
  313.         
  314.     AtomIdx = baseAtomIdx;
  315.     OperIdx = baseOperIdx;
  316.     /*ScrStatus(("*** RESULT %d undef=%d", v, *pundef));*/
  317.     return(v);
  318.     }
  319. }
  320.  
  321. void PushOp(short token, short pri, short type)
  322. {
  323.     if (pri) {
  324.     while (OperIdx > BaseOperIdx) {
  325.         Oper *op = OperStack + OperIdx - 1;
  326.         if (pri > op->Pri)
  327.         break;
  328.         if (pri == op->Pri && (type & RL))
  329.         break;
  330.         if (CombineOp() < 0) {
  331.         ScrStatus(("*** Syntax error"));
  332.         break;
  333.         }
  334.     }
  335.     }
  336.     if (OperIdx == MAXOPER) {
  337.     ScrStatus(("*** Expression too complex"));
  338.     return;
  339.     }
  340.     {
  341.     Oper *op = OperStack + OperIdx++;
  342.  
  343.     op->Pri = pri;
  344.     op->Token = token;
  345.     op->Type = type;
  346.     }
  347. }
  348.  
  349. int TopOfOpStack(void)
  350. {
  351.     if (OperIdx <= BaseOperIdx)return(-1);
  352.     return((int)OperStack[OperIdx-1].Token);
  353. }
  354.  
  355. int SecondOffOpStack(void)
  356. {
  357.     if (OperIdx - 1 <= BaseOperIdx)return(-1);
  358.     return((int)OperStack[OperIdx-2].Token);
  359. }
  360.  
  361.  
  362. void PushAtom(long val, short isundef)
  363. {
  364.     Atom *atom;
  365.  
  366.     if (AtomIdx == MAXATOM) {
  367.     ScrStatus(("*** Expression too complex"));
  368.     return;
  369.     }
  370.     atom = AtomStack + AtomIdx++;
  371.     atom->Value = val;
  372.     atom->Undef = isundef;
  373. }
  374.  
  375. static int CombineOp(void)
  376. {
  377.     Oper *op;
  378.     Atom *a1, *a2;
  379.     Atom ar;
  380.  
  381.     if (OperIdx <= BaseOperIdx)return(-1);
  382.     op = OperStack + --OperIdx;
  383.  
  384.     if (AtomIdx <= BaseAtomIdx)return(-1);
  385.     a1 = AtomStack + --AtomIdx;
  386.  
  387.     if (op->Type & QBIN) {
  388.     if (AtomIdx <= BaseAtomIdx)return(-1);
  389.     a2 = AtomStack + --AtomIdx;
  390.     }
  391.  
  392.     if (op->Type & QBIN) {
  393.     ar.Undef = a1->Undef | a2->Undef;
  394.  
  395.     switch(op->Token) {
  396.     case '+':
  397.         ar.Value = a2->Value + a1->Value;
  398.         break;
  399.     case '-':
  400.         ar.Value = a2->Value - a1->Value;
  401.         break;
  402.     case '*':
  403.         ar.Value = a2->Value * a1->Value;
  404.         break;
  405.     case '/':
  406.         if (a1->Value)ar.Value = a2->Value / a1->Value;
  407.         else ar.Undef = 1;
  408.         break;
  409.     case '%':
  410.         if (a1->Value)ar.Value = a2->Value % a1->Value;
  411.         else ar.Undef = 1;
  412.         break;
  413.     case '&':
  414.         ar.Value = a2->Value & a1->Value;
  415.         break;
  416.     case '|':
  417.         ar.Value = a2->Value | a1->Value;
  418.         break;
  419.     case '^':
  420.         ar.Value = a2->Value ^ a1->Value;
  421.         break;
  422.     case '<':
  423.         ar.Value = a2->Value < a1->Value;
  424.         break;
  425.     case CLTLT:
  426.         ar.Value = a2->Value << a1->Value;
  427.         break;
  428.     case CLTEQ:
  429.         ar.Value = a2->Value <= a1->Value;
  430.         break;
  431.     case CEQEQ:
  432.         ar.Value = a2->Value == a1->Value;
  433.         break;
  434.     case CNOTEQ:
  435.         ar.Value = a2->Value != a1->Value;
  436.         break;
  437.     case '>':
  438.         ar.Value = a2->Value > a1->Value;
  439.         break;
  440.     case CGTGT:
  441.         ar.Value = a2->Value >> a1->Value;
  442.         break;
  443.     case CGTEQ:
  444.         ar.Value = a2->Value >= a1->Value;
  445.         break;
  446.     case CANDAND:
  447.         if (a2->Value && a1->Value)
  448.         ar.Value = 1;
  449.         else
  450.         ar.Value = 0;
  451.         break;
  452.     case COROR:
  453.         if (a2->Undef == 0 && a2->Value) {
  454.         ar.Value = 1;
  455.         ar.Undef = 0;
  456.         } else if (a1->Undef == 0 && a1->Value) {
  457.         ar.Value = 1;
  458.         ar.Undef = 0;
  459.         } else {
  460.         ar.Value = 0;
  461.         }
  462.         break;
  463.     default:
  464.         ScrStatus(("*** fatal error parsing exp"));
  465.         break;
  466.     }
  467.     } 
  468.     else {
  469.     ar.Undef = a1->Undef;
  470.  
  471.     switch(op->Token) {
  472.     case '!':
  473.         ar.Value = !a1->Value;
  474.         break;
  475.     case '~':
  476.         ar.Value = ~a1->Value;
  477.         break;
  478.     case CUIND:            /*    indirect through memory */
  479.         if (a1->Value & 1) {
  480.         ar.Undef = 1;
  481.         } else {
  482.         ar.Value = *(long *)a1->Value;
  483.         }
  484.         break;
  485.     case CUMI:            /*    negate    */
  486.         ar.Value = -a1->Value;
  487.         break;
  488.     case '(':
  489.         ar.Value = a1->Value;
  490.         break;
  491.     case CDEFINED:
  492.         ar.Undef = 0;
  493.         if (a1->Undef)
  494.         ar.Value = 0;
  495.         else
  496.         ar.Value = 1;
  497.         break;
  498.     default:
  499.         ScrStatus(("*** fatal error parsing exp"));
  500.         break;
  501.     }
  502.     }
  503.     AtomStack[AtomIdx++] = ar;
  504.     /*ScrStatus(("*** op %c %03x result %d (%d)", op->Token, op->Token, ar.Value, ar.Undef));*/
  505. }
  506.  
  507. static int GetAtomStack(short *pundef, long *pv)
  508. {
  509.     Atom *at;
  510.  
  511.     if (AtomIdx <= BaseAtomIdx) {
  512.     if (pundef)*pundef = 1;
  513.     return(-1);
  514.     }
  515.     at = AtomStack + --AtomIdx;
  516.     if (pundef)*pundef = at->Undef;
  517.     if (pv)*pv = at->Value;
  518.     return(0);
  519. }
  520.  
  521. static int ParseCharConst(char *buf, long i, long max, long *pv)
  522. {
  523.     unsigned char c;
  524.     long v = 0;
  525.  
  526.     if (buf[i] != '\'')
  527.     return(0);
  528.     ++i;
  529.     while (i < max && (c = buf[i]) != '\'') {
  530.     ++i;
  531.     if (c == '\\' && i < max) {
  532.         c = buf[i++];
  533.         switch(c) {
  534.         case 'a':
  535.         c = 7;
  536.         break;
  537.         case 'b':
  538.         c = 8;
  539.         break;
  540.         case 'f':
  541.         c = 'f'&0x1F;
  542.         break;
  543.         case 'n':
  544.         c = 10;
  545.         break;
  546.         case 'r':
  547.         c = 13;
  548.         break;
  549.         case 't':
  550.         c = 9;
  551.         break;
  552.         case 'v':
  553.         c = 11;
  554.         break;
  555.         case 'x':
  556.         {
  557.             short n;
  558.             short r = 0;
  559.             short cnt = 2;
  560.  
  561.             while (cnt && (n = HexDig(c)) > 0) {
  562.             r = (r << 4) + n;
  563.             c = buf[i++];
  564.             --cnt;
  565.             }
  566.             if (cnt)
  567.             --i;
  568.             c = r;
  569.         }
  570.         break;
  571.         case '0':
  572.         case '1':
  573.         case '2':
  574.         case '3':
  575.         case '4':
  576.         case '5':
  577.         case '6':
  578.         case '7':
  579.         case '8':
  580.         case '9':
  581.         {
  582.             short cnt;
  583.             short r;
  584.             short n;
  585.  
  586.             for (r = cnt = 0; cnt < 3 && (n = OctDig(c)) >= 0; ++cnt) {
  587.             r = (r << 3) + n;
  588.             c = buf[i++];
  589.             }
  590.             --i;
  591.             c = r;
  592.         }
  593.         break;
  594.         default:
  595.         c = buf[i];
  596.         break;
  597.         }
  598.     }
  599.     v = (v << 8) | c;
  600.     }
  601.     *pv = v;
  602.     if (i < max) ++i;   /*    skip closing single quote   */
  603.     
  604.     else ScrStatus(("*** unterminated char const"));
  605.     return(i);
  606. }
  607.  
  608. /*
  609.  *  0xhex
  610.  *  0octal
  611.  *  1-9decimal
  612.  */
  613.  
  614. static int ParseInt(char *buf, long i, long max, long *pv)
  615. {
  616.     char c;
  617.     long v = 0;
  618.  
  619.     if (i < max && buf[i] == '0') {
  620.     ++i;
  621.     if (i < max && (buf[i] == 'x' || buf[i] == 'X')) {   /*  hex */
  622.         short n;
  623.         ++i;
  624.         while (i < max && (n = HexDig(buf[i])) >= 0) {
  625.         v = (v << 4) + n;
  626.         ++i;
  627.         }
  628.     } 
  629.     else {                         /*  oct */
  630.         short n;
  631.         while (i < max && (n = OctDig(buf[i])) >= 0) {
  632.         v = (v << 3) + n;
  633.         ++i;
  634.         }
  635.     }
  636.     }
  637.     else {
  638.     while (i < max && (c = buf[i]) >= '0' && c <= '9') { /*  dec */
  639.         v = v * 10 + c - '0';
  640.         ++i;
  641.     }
  642.     }
  643.     while ((c = buf[i]) == 'L' || c == 'l' || c == 'U' || c == 'u')++i;
  644.  
  645.     // if a . follows the number, its a line number;  so find the
  646.     // address associated with it
  647.     if((buf[i] == '.') && (CurDisplay->ds_DisplayMode <= DISPLAY_LONGS)) {
  648.     ULONG address, line ,info[2];
  649.  
  650.     i++;
  651.         address = CurDisplay->ds_WindowTop;
  652.     line = 0;
  653.         CurrentMixedLine(&address,&line,info);
  654.  
  655.         while(info[1] < v) {
  656.         NextMixedLine(&address,&line,info);
  657.     }
  658.     v = address;
  659.     }
  660.     *pv = v;
  661.     return(i);
  662. }
  663.  
  664. static int HexDig(char c)
  665. {
  666.     if (c >= '0' && c <= '9')return (c - '0');
  667.     if (c >= 'a' && c <= 'f')c = c + ('A' - 'a');
  668.     if (c >= 'A' && c <= 'F')return (c + (10 - 'A'));
  669.     return(-1);
  670. }
  671.  
  672. static int OctDig(char c)
  673. {
  674.     if (c >= '0' && c <= '7')return (c - '0');
  675.     return(-1);
  676. }
  677.  
  678.  
  679. /*
  680.  *  Random support
  681.  */
  682.  
  683. short SymbolChar(short c)
  684. {
  685.     if (c >= '0' && c <= '9')return(1);
  686.     if (c >= 'a' && c <= 'z')return(1);
  687.     if (c >= 'A' && c <= 'Z')return(1);
  688.     if (c == '_' || c == '@')return(1);
  689.     return(0);
  690. }
  691.  
  692. long ExtSymbol(unsigned char *base, long i, long max)
  693. {
  694.     long b = i;
  695.  
  696.     while (i < max && SymbolChar(base[i]))++i;
  697.     return(i);
  698. }
  699.  
  700.  
  701.  
  702. #ifdef MYKE_REMOVED_THIS
  703.  
  704. typedef struct Sym {
  705.     char    *Name;
  706.     char    *Text;
  707.     long    TextLen;
  708. } Sym;
  709.  
  710. Local Sym *FindSymbol(char *, short);
  711. Sym *FindSymbol(char *name, short nameLen)
  712. {
  713.     static Sym SymAry[] = {
  714.     {   "a", "b+3"  , 3   },
  715.     {   "b", "4"    , 1   }
  716.     };
  717.     Sym *sym;
  718.  
  719.     for (sym = SymAry; sym < SymAry + (sizeof(SymAry)/sizeof(SymAry[0])); ++sym) {
  720.     if (strlen(sym->Name) == nameLen && strnicmp(name, sym->Name, nameLen) == 0)
  721.         return(sym);
  722.     }
  723.     return(NULL);
  724. }
  725. #endif